use std::sync::atomic::{AtomicUsize, Ordering};
macro_rules! assert_test {
    ($ expr : expr) => {
        NUM_ASSERT.fetch_add(1, Ordering::SeqCst);
        if !$expr {
            __assert_fail(stringify!($expr), file!(), line!(), function!());
        }
    };
}
const RB_TREE_NULL: *const std::ffi::c_void = std::ptr::null();
const NUM_TEST_VALUES: usize = 1000;
type UnitTestFunction = fn();
type RBTreeKey = *mut std::ffi::c_void;
type RBTreeValue = *mut std::ffi::c_void;
type RBTreeCompareFunc = fn(RBTreeValue, RBTreeValue) -> i32;
static NUM_ASSERT: AtomicUsize = AtomicUsize::new(0);
#[repr(C)]
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq)]
enum RBTreeNodeColor {
    RB_TREE_NODE_RED,
    RB_TREE_NODE_BLACK,
}
static TESTS: &[Option<UnitTestFunction>] = &[
    Some(test_rb_tree_new),
    Some(test_rb_tree_free),
    Some(test_rb_tree_child),
    Some(test_rb_tree_insert_lookup),
    Some(test_rb_tree_lookup),
    Some(test_out_of_memory),
    None,
];
fn find_subtree_height(node: Option<Box<RBTreeNode>>) -> i32 {
    if node.is_none() {
        return 0;
    }
    let left_subtree = rb_tree_node_child(&node, "RB_TREE_NODE_LEFT");
    let right_subtree = rb_tree_node_child(&node, "RB_TREE_NODE_RIGHT");
    let left_height = find_subtree_height(left_subtree);
    let right_height = find_subtree_height(right_subtree);
    if left_height > right_height {
        left_height + 1
    } else {
        right_height + 1
    }
}
fn create_tree() -> *mut RBTree {
    let tree = rb_tree_new(int_compare);
    for i in 0..NUM_TEST_VALUES {
        TEST_ARRAY[i] = i as i32;
        rb_tree_insert(tree, &TEST_ARRAY[i], &TEST_ARRAY[i]);
    }
    tree
}
#[test]
fn test_rb_tree_new() {
    let tree = create_tree();
    let mut i: i32;
    let mut x: i32;
    let mut y: i32;
    let mut z: i32;
    let mut value: i32;
    let mut expected_entries: i32;
    i = NUM_TEST_VALUES + 100;
    assert!(rb_tree_remove(tree, &i) == 0);
    i = -1;
    assert!(rb_tree_remove(tree, &i) == 0);
    expected_entries = NUM_TEST_VALUES;
    for x in 0..10 {
        for y in 0..10 {
            for z in 0..10 {
                value = z * 100 + (9 - y) * 10 + x;
                assert!(rb_tree_remove(tree, &value) != 0);
                validate_tree(tree);
                expected_entries -= 1;
                assert!(rb_tree_num_entries(tree) == expected_entries);
            }
        }
    }
    assert!(rb_tree_root_node(tree).is_null());
    rb_tree_free(tree);
}
#[test]
fn test_out_of_memory() {
    use std::assert;
    use std::ptr;
    struct RBTree {}
    struct RBTreeNode {}
    unsafe {
        let mut tree: *mut RBTree = create_tree();
        alloc_test_set_limit(0);
        for i in 10000..20000 {
            let node = rb_tree_insert(
                tree,
                &i as *const i32 as *const std::ffi::c_void,
                &i as *const i32 as *const std::ffi::c_void,
            );
            assert!(node.is_null());
            validate_tree(tree);
        }
        rb_tree_free(tree);
    }
}
#[test]
fn test_rb_tree_lookup() {
    let mut tree = create_tree();
    for i in 0..NUM_TEST_VALUES {
        let value = rb_tree_lookup(&tree, &(i as i32));
        assert!(value.is_some());
        assert!(*(value.unwrap()) == i as i32);
    }
    let mut i = -1;
    assert!(rb_tree_lookup(&tree, &i).is_none());
    i = NUM_TEST_VALUES as i32 + 1;
    assert!(rb_tree_lookup(&tree, &i).is_none());
    i = 8724897;
    assert!(rb_tree_lookup(&tree, &i).is_none());
    rb_tree_free(tree);
}
#[test]
fn test_rb_tree_to_array() {
    let tree = unsafe { rb_tree_new(int_compare) };
    let entries = [89, 23, 42, 4, 16, 15, 8, 99, 50, 30];
    let sorted = [4, 8, 15, 16, 23, 30, 42, 50, 89, 99];
    let num_entries = entries.len();
    for entry in &entries {
        unsafe {
            rb_tree_insert(tree, entry, ptr::null_mut());
        }
    }
    assert_eq!(unsafe { rb_tree_num_entries(tree) }, num_entries);
    let array = unsafe { rb_tree_to_array(tree) };
    for i in 0..num_entries {
        assert_eq!(unsafe { *array.add(i).read() }, sorted[i]);
    }
    unsafe {
        free(array as *mut c_void);
    }
    alloc_test_set_limit(0);
    let array = unsafe { rb_tree_to_array(tree) };
    assert_eq!(array, ptr::null_mut());
    validate_tree(tree);
    unsafe {
        rb_tree_free(tree);
    }
}
fn main() {
    let args: Vec<String> = env::args().collect();
    let tests: Vec<fn()> = vec![];
    run_tests(&tests);
    println!("num_assert: {}", NUM_ASSERT.load(Ordering::SeqCst));
}
